/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// Created on 09.12.2003 by RST.
// $Id: Math3D.java,v 1.9 2005/02/20 21:50:36 salomo Exp $
using System;
using Defines = Suake2.UI.Defines;
using cplane_t = Suake2.UI.game.cplane_t;
using Com = Suake2.UI.qcommon.Com;
namespace Suake2.UI.util
{
	
	public class Math3D
	{
		
		internal const float shortratio = 360.0f / 65536.0f;
		//UPGRADE_NOTE: Final was removed from the declaration of 'piratio '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
		internal static readonly float piratio = (float) (System.Math.PI / 360.0);
		public static void  set_Renamed(float[] v1, float[] v2)
		{
			v1[0] = v2[0];
			v1[1] = v2[1];
			v1[2] = v2[2];
		}
		public static void  VectorSubtract(float[] a, float[] b, float[] c)
		{
			c[0] = a[0] - b[0];
			c[1] = a[1] - b[1];
			c[2] = a[2] - b[2];
		}
		public static void  VectorSubtract(short[] a, short[] b, int[] c)
		{
			c[0] = a[0] - b[0];
			c[1] = a[1] - b[1];
			c[2] = a[2] - b[2];
		}
		public static void  VectorAdd(float[] a, float[] b, float[] to)
		{
			to[0] = a[0] + b[0];
			to[1] = a[1] + b[1];
			to[2] = a[2] + b[2];
		}
		public static void  VectorCopy(float[] from, float[] to)
		{
			to[0] = from[0];
			to[1] = from[1];
			to[2] = from[2];
		}
		public static void  VectorCopy(short[] from, short[] to)
		{
			to[0] = from[0];
			to[1] = from[1];
			to[2] = from[2];
		}
		public static void  VectorCopy(short[] from, float[] to)
		{
			to[0] = from[0];
			to[1] = from[1];
			to[2] = from[2];
		}
		public static void  VectorCopy(float[] from, short[] to)
		{
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			to[0] = (short) from[0];
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			to[1] = (short) from[1];
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			to[2] = (short) from[2];
		}
		public static void  VectorClear(float[] a)
		{
			a[0] = a[1] = a[2] = 0;
		}
		public static bool VectorEquals(float[] v1, float[] v2)
		{
			if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
				return false;
			
			return true;
		}
		public static void  VectorNegate(float[] from, float[] to)
		{
			to[0] = - from[0];
			to[1] = - from[1];
			to[2] = - from[2];
		}
		public static void  VectorSet(float[] v, float x, float y, float z)
		{
			v[0] = (x);
			v[1] = (y);
			v[2] = (z);
		}
		public static void  VectorMA(float[] veca, float scale, float[] vecb, float[] to)
		{
			to[0] = veca[0] + scale * vecb[0];
			to[1] = veca[1] + scale * vecb[1];
			to[2] = veca[2] + scale * vecb[2];
		}
		public static float VectorNormalize(float[] v)
		{
			
			float length = VectorLength(v);
			if (length != 0.0f)
			{
				float ilength = 1.0f / length;
				v[0] *= ilength;
				v[1] *= ilength;
				v[2] *= ilength;
			}
			return length;
		}
		public static float VectorLength(float[] v)
		{
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			return (float) System.Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
		}
		public static void  VectorInverse(float[] v)
		{
			v[0] = - v[0];
			v[1] = - v[1];
			v[2] = - v[2];
		}
		public static void  VectorScale(float[] in_Renamed, float scale, float[] out_Renamed)
		{
			out_Renamed[0] = in_Renamed[0] * scale;
			out_Renamed[1] = in_Renamed[1] * scale;
			out_Renamed[2] = in_Renamed[2] * scale;
		}
		public static float vectoyaw(float[] vec)
		{
			float yaw;
			
			if (vec[Defines.PITCH] == 0)
			{
				yaw = 0;
				if (vec[Defines.YAW] > 0)
					yaw = 90;
				else if (vec[Defines.YAW] < 0)
					yaw = - 90;
			}
			else
			{
				
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				yaw = (int) (System.Math.Atan2(vec[Defines.YAW], vec[Defines.PITCH]) * 180 / System.Math.PI);
				if (yaw < 0)
					yaw += 360;
			}
			
			return yaw;
		}
		public static void  vectoangles(float[] value1, float[] angles)
		{
			
			float yaw, pitch;
			
			if (value1[1] == 0 && value1[0] == 0)
			{
				yaw = 0;
				if (value1[2] > 0)
					pitch = 90;
				else
					pitch = 270;
			}
			else
			{
				if (value1[0] != 0)
				{
					//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
					yaw = (int) (System.Math.Atan2(value1[1], value1[0]) * 180 / System.Math.PI);
				}
				else if (value1[1] > 0)
					yaw = 90;
				else
					yaw = - 90;
				if (yaw < 0)
					yaw += 360;
				
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				float forward = (float) System.Math.Sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				pitch = (int) (System.Math.Atan2(value1[2], forward) * 180 / System.Math.PI);
				if (pitch < 0)
					pitch += 360;
			}
			
			angles[Defines.PITCH] = - pitch;
			angles[Defines.YAW] = yaw;
			angles[Defines.ROLL] = 0;
		}
		private static float[][] m = new float[3][];
		private static float[][] im = new float[3][];
		private static float[][] tmpmat = new float[3][];
		private static float[][] zrot = new float[3][];
		
		// to reduce garbage
		//UPGRADE_NOTE: Final was removed from the declaration of 'vr'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly float[] vr = new float[]{0, 0, 0};
		//UPGRADE_NOTE: Final was removed from the declaration of 'vup'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly float[] vup = new float[]{0, 0, 0};
		//UPGRADE_NOTE: Final was removed from the declaration of 'vf'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly float[] vf = new float[]{0, 0, 0};
		
		public static void  RotatePointAroundVector(float[] dst, float[] dir, float[] point, float degrees)
		{
			vf[0] = dir[0];
			vf[1] = dir[1];
			vf[2] = dir[2];
			
			PerpendicularVector(vr, dir);
			CrossProduct(vr, vf, vup);
			
			m[0][0] = vr[0];
			m[1][0] = vr[1];
			m[2][0] = vr[2];
			
			m[0][1] = vup[0];
			m[1][1] = vup[1];
			m[2][1] = vup[2];
			
			m[0][2] = vf[0];
			m[1][2] = vf[1];
			m[2][2] = vf[2];
			
			im[0][0] = m[0][0];
			im[0][1] = m[1][0];
			im[0][2] = m[2][0];
			im[1][0] = m[0][1];
			im[1][1] = m[1][1];
			im[1][2] = m[2][1];
			im[2][0] = m[0][2];
			im[2][1] = m[1][2];
			im[2][2] = m[2][2];
			
			zrot[0][2] = zrot[1][2] = zrot[2][0] = zrot[2][1] = 0.0f;
			
			zrot[2][2] = 1.0F;
			
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			zrot[0][0] = zrot[1][1] = (float) System.Math.Cos(DEG2RAD(degrees));
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			zrot[0][1] = (float) System.Math.Sin(DEG2RAD(degrees));
			zrot[1][0] = - zrot[0][1];
			
			R_ConcatRotations(m, zrot, tmpmat);
			R_ConcatRotations(tmpmat, im, zrot);
			
			for (int i = 0; i < 3; i++)
			{
				dst[i] = zrot[i][0] * point[0] + zrot[i][1] * point[1] + zrot[i][2] * point[2];
			}
		}
		
		public static void  MakeNormalVectors(float[] forward, float[] right, float[] up)
		{
			// this rotate and negat guarantees a vector
			// not colinear with the original
			right[1] = - forward[0];
			right[2] = forward[1];
			right[0] = forward[2];
			
			float d = DotProduct(right, forward);
			VectorMA(right, - d, forward, right);
			VectorNormalize(right);
			CrossProduct(right, forward, up);
		}
		public static float SHORT2ANGLE(int x)
		{
			return (x * shortratio);
		}
		/*
		================
		R_ConcatTransforms
		================
		*/
		public static void  R_ConcatTransforms(float[][] in1, float[][] in2, float[][] out_Renamed)
		{
			out_Renamed[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
			out_Renamed[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
			out_Renamed[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
			out_Renamed[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
			out_Renamed[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
			out_Renamed[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
			out_Renamed[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
			out_Renamed[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
			out_Renamed[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
			out_Renamed[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
			out_Renamed[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
			out_Renamed[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
		}
		/// <summary> concatenates 2 matrices each [3][3].</summary>
		public static void  R_ConcatRotations(float[][] in1, float[][] in2, float[][] out_Renamed)
		{
			out_Renamed[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
			out_Renamed[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
			out_Renamed[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
			out_Renamed[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
			out_Renamed[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
			out_Renamed[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
			out_Renamed[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
			out_Renamed[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
			out_Renamed[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
		}
		public static void  ProjectPointOnPlane(float[] dst, float[] p, float[] normal)
		{
			
			float inv_denom = 1.0F / DotProduct(normal, normal);
			
			float d = DotProduct(normal, p) * inv_denom;
			
			dst[0] = normal[0] * inv_denom;
			dst[1] = normal[1] * inv_denom;
			dst[2] = normal[2] * inv_denom;
			
			dst[0] = p[0] - d * dst[0];
			dst[1] = p[1] - d * dst[1];
			dst[2] = p[2] - d * dst[2];
		}
		
		//UPGRADE_NOTE: Final was removed from the declaration of 'PLANE_XYZ'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly float[][] PLANE_XYZ = new float[][]{new float[]{1, 0, 0}, new float[]{0, 1, 0}, new float[]{0, 0, 1}};
		
		/// <summary>assumes "src" is normalized </summary>
		public static void  PerpendicularVector(float[] dst, float[] src)
		{
			int pos;
			int i;
			float minelem = 1.0F;
			
			// find the smallest magnitude axially aligned vector 
			for (pos = 0, i = 0; i < 3; i++)
			{
				if (System.Math.Abs(src[i]) < minelem)
				{
					pos = i;
					minelem = System.Math.Abs(src[i]);
				}
			}
			// project the point onto the plane defined by src
			ProjectPointOnPlane(dst, PLANE_XYZ[pos], src);
			
			//normalize the result 
			VectorNormalize(dst);
		}

		//=====================================================================	
		/// <summary>stellt fest, auf welcher Seite sich die Kiste befindet, wenn die Ebene 
		/// durch Entfernung und Senkrechten-Normale gegeben ist.    
		/// erste Version mit vec3_t... 
		/// </summary>
		public static int BoxOnPlaneSide(float[] emins, float[] emaxs, cplane_t p)
		{
			
			//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
            // HZ:
            // - aca esta la definicion de asertos http://www.webtaller.com/construccion/lenguajes/java/lecciones/introduccion-asertos-java.php
            // - http://bytes.com/forum/thread274690.html
            // - http://www.csharpfriends.com/articles/getarticle.aspx?articleid=16 (implementa metodo assert)
			assert(emins.length == 3 && emaxs.length == 3): vec3_t bug;
			
			float dist1, dist2;
			int sides;
			
			//	   fast axial cases
			if (p.type < 3)
			{
				if (p.dist <= emins[p.type])
					return 1;
				if (p.dist >= emaxs[p.type])
					return 2;
				return 3;
			}
			
			//	   general case
			switch (p.signbits)
			{
				
				case 0: 
					dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
					dist2 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
					break;
				
				case 1: 
					dist1 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
					dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
					break;
				
				case 2: 
					dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
					dist2 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
					break;
				
				case 3: 
					dist1 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
					dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
					break;
				
				case 4: 
					dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
					dist2 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
					break;
				
				case 5: 
					dist1 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
					dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
					break;
				
				case 6: 
					dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
					dist2 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
					break;
				
				case 7: 
					dist1 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
					dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
					break;
				
				default: 
					dist1 = dist2 = 0;
					//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
					assert(false): BoxOnPlaneSide bug;
					break;
				
			}
			
			sides = 0;
			if (dist1 >= p.dist)
				sides = 1;
			if (dist2 < p.dist)
				sides |= 2;
			
			//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
			assert(sides != 0): BoxOnPlaneSide(): sides == 0 bug;
			
			return sides;
		}
		//	this is the slow, general version
		private static float[][] corners = new float[2][];
		public static int BoxOnPlaneSide2(float[] emins, float[] emaxs, cplane_t p)
		{
			
			for (int i = 0; i < 3; i++)
			{
				if (p.normal[i] < 0)
				{
					corners[0][i] = emins[i];
					corners[1][i] = emaxs[i];
				}
				else
				{
					corners[1][i] = emins[i];
					corners[0][i] = emaxs[i];
				}
			}
			float dist1 = DotProduct(p.normal, corners[0]) - p.dist;
			float dist2 = DotProduct(p.normal, corners[1]) - p.dist;
			int sides = 0;
			if (dist1 >= 0)
				sides = 1;
			if (dist2 < 0)
				sides |= 2;
			
			return sides;
		}
		public static void  AngleVectors(float[] angles, float[] forward, float[] right, float[] up)
		{
			
			float cr = 2.0f * piratio;
			float angle = (float) (angles[Defines.YAW] * (cr));
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			float sy = (float) System.Math.Sin(angle);
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			float cy = (float) System.Math.Cos(angle);
			angle = (float) (angles[Defines.PITCH] * (cr));
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			float sp = (float) System.Math.Sin(angle);
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			float cp = (float) System.Math.Cos(angle);
			
			if (forward != null)
			{
				forward[0] = cp * cy;
				forward[1] = cp * sy;
				forward[2] = - sp;
			}
			
			if (right != null || up != null)
			{
				angle = (float) (angles[Defines.ROLL] * (cr));
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				float sr = (float) System.Math.Sin(angle);
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				cr = (float) System.Math.Cos(angle);
				
				if (right != null)
				{
					right[0] = ((- sr) * sp * cy + cr * sy);
					right[1] = ((- sr) * sp * sy + (- cr) * cy);
					right[2] = (- sr) * cp;
				}
				if (up != null)
				{
					up[0] = (cr * sp * cy + sr * sy);
					up[1] = (cr * sp * sy + (- sr) * cy);
					up[2] = cr * cp;
				}
			}
		}
		public static void  G_ProjectSource(float[] point, float[] distance, float[] forward, float[] right, float[] result)
		{
			result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1];
			result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1];
			result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
		}
		public static float DotProduct(float[] x, float[] y)
		{
			return x[0] * y[0] + x[1] * y[1] + x[2] * y[2];
		}
		public static void  CrossProduct(float[] v1, float[] v2, float[] cross)
		{
			cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
			cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
			cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
		}
		public static int Q_log2(int val)
		{
			int answer = 0;
			while ((val >>= 1) > 0)
				answer++;
			return answer;
		}
		public static float DEG2RAD(float in_Renamed)
		{
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			return (in_Renamed * (float) System.Math.PI) / 180.0f;
		}
		public static float anglemod(float a)
		{
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			return (float) (shortratio) * ((int) (a / (shortratio)) & 65535);
		}
		public static int ANGLE2SHORT(float x)
		{
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			return ((int) ((x) / shortratio) & 65535);
		}
		public static float LerpAngle(float a2, float a1, float frac)
		{
			if (a1 - a2 > 180)
				a1 -= 360;
			if (a1 - a2 < - 180)
				a1 += 360;
			return a2 + frac * (a1 - a2);
		}
		public static float CalcFov(float fov_x, float width, float height)
		{
			double a = 0.0f;
			double x;
			
			if (fov_x < 1.0f || fov_x > 179.0f)
				Com.Error(Defines.ERR_DROP, "Bad fov: " + fov_x);
			
			x = width / System.Math.Tan(fov_x * piratio);
			
			a = System.Math.Atan(height / x);
			
			a = a / piratio;
			
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			return (float) a;
		}
		static Math3D()
		{
			for (int i = 0; i < 3; i++)
			{
				m[i] = new float[3];
			}
			for (int i2 = 0; i2 < 3; i2++)
			{
				im[i2] = new float[3];
			}
			for (int i3 = 0; i3 < 3; i3++)
			{
				tmpmat[i3] = new float[3];
			}
			for (int i4 = 0; i4 < 3; i4++)
			{
				zrot[i4] = new float[3];
			}
			for (int i = 0; i < 2; i++)
			{
				corners[i] = new float[3];
			}
		}
	}
}